﻿using DllSampleAll;
using HalconDotNet;
using LJV7_DllSampleAll;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FocalSpec.GuiExample.Model;
using System.Drawing;

namespace NDK.AcqDevice.Keyence
{
    public class LJLaser : ILineLaser
    {

        /// <summary>
        /// 采集帧数，只对线扫设备有效
        /// </summary>
        public int m_NeededProfile { get; set; }

        /// <summary>
        /// 采集帧数，只对线扫设备有效
        /// </summary>
        protected int m_CurrentProfile = 0;

        [NonSerialized]
        public bool m_bEnableRevData = false;//回调函数时，是否允许接受数据

        private HImage heightImage;
        private HImage luminanceImage;
        private AutoResetEvent heightImageEvent = new AutoResetEvent(false);
        private AutoResetEvent luminanceImageEvent = new AutoResetEvent(false);
        public HImage HeightImage(int timeout = 3000)
        {
            if (heightImageEvent.WaitOne(timeout) == true)
            {
                if (heightImage.IsInitialized())
                {
                    return heightImage.CopyImage();
                }
            }

            return null;
        }
        public HImage LuminanceImage(int timeout = 3000)
        {
            if (luminanceImageEvent.WaitOne(timeout) == true)
            {
                if (luminanceImage.IsInitialized())
                {
                    return luminanceImage.CopyImage();
                }
            }
            return null;
        }



        bool m_bConnected = false;
        public bool IsConnected
        {
            get
            {
                return m_bConnected;
            }
        }

        public static int DEVICE_COUNT = 0;
        /// <summary>Device ID (fixed to 0)</summary>
        private int DEVICE_ID = 0;//0~5

        /// <summary>Ethernet communication settings</summary>
        public string m_UniqueLabel
        {
            get { return ethernetConfig.abyIpAddress.ToString() + ":" + ethernetConfig.wPortNo.ToString(); }
            set
            {
                //设置keyence ip地址
                string[] ipInfo = value.Split(':');
                string[] keyenceIp = ipInfo[0].Split('.');
                ethernetConfig.abyIpAddress = new byte[] {
                Convert.ToByte(keyenceIp[0]),
                Convert.ToByte(keyenceIp[1]),
                Convert.ToByte(keyenceIp[2]),
                Convert.ToByte(keyenceIp[3])
                };
                ethernetConfig.wPortNo = (ushort)(int.Parse(ipInfo[1]));
                highSpeedPort = (ushort)(ethernetConfig.wPortNo + 1);
            }
        }

        /// <summary>Ethernet communication port settings</summary>
        private UInt16 _highSpeedPort;

        /// <summary>connection mode 默认1  0 -USB 连接模式 1 - 高速网口连接模式，</summary>
        private int _connectMode = 1;

        /// <summary>批处理多少帧回调一次，默认每帧回调一次，设置单帧回调，目的是避免存留在内存里</summary>
        private uint _profileFrequence = 1;

        /// <summary>High-speed communication start profileNO</summary>
        private byte _StartProfileNo = 0;

        /// <summary>量程上下限</summary>
        private double LimitMin = -7.5;
        private double LimitMax = 7.5;

        /// <summary>
        /// 输出数据模式，0- 返回所有数据 1- 返回第一个镭射数据，2 -返回第二个镭射数据
        /// </summary>
        private int _outDataMode = 0;

        /// <summary>High-speed communication callback function</summary>
        [NonSerialized]
        private HighSpeedDataCallBack _callback;

        /// <summary>the size of header and footer</summary>
        //[NonSerialized]
        //int headerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_HEADER)) / sizeof(int);
        //[NonSerialized]
        //int footerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_FOOTER)) / sizeof(int);

        LJV7IF_PROFILE_INFO profileInfo = new LJV7IF_PROFILE_INFO();
        LJV7IF_HIGH_SPEED_PRE_START_REQ req = new LJV7IF_HIGH_SPEED_PRE_START_REQ();
        //图像指针内存

        //IntPtr Imagebuffer;
        //int[] reciveBuffer;

        ///// <summary>统计接收到的帧数</summary>
        //private int _receiveCount = 0;

        /// <summary>
        /// 基恩士激光网卡设置
        /// </summary>
        private LJV7IF_ETHERNET_CONFIG ethernetConfig;
        private int m_curBatchNo;

        //高速采集网络端口号
        public UInt16 highSpeedPort
        {
            get { return _highSpeedPort; }
            set { _highSpeedPort = value; }
        }
        //连接模式
        public int connectMode
        {
            get { return _connectMode; }
            set { _connectMode = value; }
        }
        //采集频率
        public uint frequence
        {
            get { return _profileFrequence; }
            set { _profileFrequence = value; }
        }
        //开始采集位置
        public byte StartProfileNo
        {
            get { return _StartProfileNo; }
            set { _StartProfileNo = value; }
        }
        /// <summary>
        /// 返回数据模式
        /// </summary>
        public int OutDataMode
        {
            get { return _outDataMode; }
            set { _outDataMode = value; }
        }


        public LJLaser(int devID, string ip = "192.168.0.15", ushort portNo = 24691, ushort highSpeedPortNo = 24692)
        {
            DEVICE_ID = devID;
            string[] ips = ip.Split('.');

            byte[] ipAddress = new byte[4];
            if (!byte.TryParse(ips[0], out ipAddress[0]) ||
                !byte.TryParse(ips[1], out ipAddress[1]) ||
                !byte.TryParse(ips[2], out ipAddress[2]) ||
                !byte.TryParse(ips[3], out ipAddress[3]))
            {
                Debug.WriteLine("LJ激光IP格式不正确!");
                return;
            }

            ethernetConfig.abyIpAddress = ipAddress;
            ethernetConfig.wPortNo = portNo;

            highSpeedPort = highSpeedPortNo;
            req = new LJV7IF_HIGH_SPEED_PRE_START_REQ();
            req.bySendPos = Convert.ToByte("2");
            //

        }

        /// <summary>
        ///停止中断设备连接
        ////// <summary>
        public void DisConnect()
        {
            try
            {
                //Marshal.FreeHGlobal(Imagebuffer);
                //reciveBuffer = null;

                Rc rc = Rc.Ok;

                // Stop high-speed data communication.
                rc = (Rc)NativeMethods.LJV7IF_StopHighSpeedDataCommunication(DEVICE_ID);
                if (CheckReturnCode(rc))
                {
                    // Exit high-speed data communication.
                    rc = (Rc)NativeMethods.LJV7IF_HighSpeedDataCommunicationFinalize(DEVICE_ID);
                    if (CheckReturnCode(rc))
                    {
                        rc = (Rc)NativeMethods.LJV7IF_CommClose(DEVICE_ID);
                        if (CheckReturnCode(rc))
                        {
                            rc = (Rc)NativeMethods.LJV7IF_Finalize();
                            m_bConnected = false;
                        }
                    }
                }
            }
            catch (Exception)
            {

            }
        }

        /// <summary>
        /// The check of a return code 
        /// </summary>
        /// <param name="rc">Return code </param>
        /// <returns>OK or not</returns>
        /// <remarks>If not OK, return false after displaying message.</remarks>
        private bool CheckReturnCode(Rc rc)
        {
            if (rc == Rc.Ok) return true;
            //MessageBox.Show(string.Format("Error: 0x{0,8:x}", rc), "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
        /// <summary>
        /// 开始采集数据
        /// </summary>
        public Boolean InitDevice()
        {
            try
            {
                Rc rc = Rc.Ok;
                //clear all data in buffer
                rc = (Rc)NativeMethods.LJV7IF_ClearMemory(DEVICE_ID);
                if (CheckReturnCode(rc))
                {
                    rc = (Rc)NativeMethods.LJV7IF_StopHighSpeedDataCommunication(DEVICE_ID);
                    if (CheckReturnCode(rc))
                    {
                        rc = (Rc)NativeMethods.LJV7IF_HighSpeedDataCommunicationFinalize(DEVICE_ID);
                        if (CheckReturnCode(rc))
                        {

                            uint threadId = (uint)(DEVICE_ID + 1);

                            _callback = new HighSpeedDataCallBack(ReceiveData);
                            if (_connectMode == 0)
                            {
                                // Initialize USB high-speed data communication
                                rc = (Rc)NativeMethods.LJV7IF_HighSpeedDataUsbCommunicationInitalize(DEVICE_ID, _callback, frequence, threadId);
                            }
                            else if (_connectMode == 1)
                            {
                                // Initialize Ethernet high-speed data communication
                                rc = (Rc)NativeMethods.LJV7IF_HighSpeedDataEthernetCommunicationInitalize(DEVICE_ID, ref ethernetConfig,
                                    highSpeedPort, _callback, frequence, threadId);
                            }
                            if (CheckReturnCode(rc))
                            {

                                // High-speed data communication start prep
                                rc = (Rc)NativeMethods.LJV7IF_PreStartHighSpeedDataCommunication(DEVICE_ID, ref req, ref profileInfo);

                                if (CheckReturnCode(rc))
                                {
                                    rc = (Rc)NativeMethods.LJV7IF_StartHighSpeedDataCommunication(DEVICE_ID);
                                    if (CheckReturnCode(rc))
                                    {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }

                return false;

                //接受到连接信息后初始化
                //Imagebuffer = Marshal.AllocHGlobal(m_NeededProfile * (DEVICE_ID + 1) * profileInfo.wProfDataCnt * sizeof(int));
                //reciveBuffer = new int[profileInfo.wProfDataCnt * (DEVICE_ID + 1) * m_NeededProfile];
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        public bool Connect(string id)
        {

            DisConnect();
            Rc rc = Rc.Ok;
            // Initialize the DLL.
            rc = (Rc)NativeMethods.LJV7IF_Initialize();
            if (CheckReturnCode(rc))
            {
                // Open communication path.
                if (connectMode == 0)
                {
                    rc = (Rc)NativeMethods.LJV7IF_UsbOpen(DEVICE_ID);
                }
                else if (connectMode == 1)
                {
                    rc = (Rc)NativeMethods.LJV7IF_EthernetOpen(DEVICE_ID, ref ethernetConfig);
                    if (rc != Rc.Ok)
                    {
                        rc = (Rc)NativeMethods.LJV7IF_EthernetOpen(DEVICE_ID, ref ethernetConfig);
                    }
                }

                if (CheckReturnCode(rc))
                {
                    if (InitDevice())
                    {
                        m_bConnected = true;
                        return true;
                    }
                }
            }
            return false;

        }
        /// <summary>
        /// High-speed communication callback process
        /// </summary>
        /// <param name="buffer">Pointer to beginning of received data</param>
        /// <param name="size">Byte size per 1 profile in received data</param>
        /// <param name="count">Profile count</param>
        /// <param name="notify">Exited or not</param>
        /// <param name="user">Information passed when high-speed data communication was initialized (thread ID)</param>
        private void ReceiveData(IntPtr buffer, uint size, uint count, uint notify, uint user)
        {
            try
            {
                if (notify != 0)
                {
                    if (Convert.ToBoolean(notify & 0x08))
                    {
                        NativeMethods.LJV7IF_StopMeasure(DEVICE_ID);
                    }
                }


                if (count == 0 || size == 0)
                    return;


                uint profileSize = (uint)(size / Marshal.SizeOf(typeof(int)));   //轮廓宽度

                List<int[]> receiveBuffer = new List<int[]>();
                int[] bufferArray = new int[profileSize * count];
                Marshal.Copy(buffer, bufferArray, 0, (int)(profileSize * count));

                // Profile data retention
                for (int i = 0; i < count; i++)
                {
                    int[] oneProfile = new int[profileSize];
                    Array.Copy(bufferArray, i * profileSize, oneProfile, 0, profileSize);
                    receiveBuffer.Add(oneProfile);
                }

                ThreadSafeBuffer.Add((int)user, receiveBuffer, notify);

                if (notify != 0)
                {
                    if (notify == 0x10000)
                    {
                        NativeMethods.LJV7IF_StopMeasure(DEVICE_ID);
                        System.Console.Write("数据接收完成!\n");
                        int batcnNo = 0;

                        List<int[]> data = ThreadSafeBuffer.Get(DEVICE_ID, out notify, out batcnNo);


                        using (PinnedObject pin = new PinnedObject(data))
                        {
                            IntPtr bufferPointer = pin.Pointer;

                            heightImage = new HImage();
                            heightImage.GenImage1("int4", (int)profileSize, data.Count, bufferPointer);
                            heightImage = heightImage.ConvertImageType("real");
                            heightImage = heightImage.ScaleImage(1 / 100000.0, 0);
                        }
                        m_curBatchNo = 0;
                        heightImageEvent.Set();
                        ThreadSafeBuffer.ClearBuffer(DEVICE_ID);
                    }
                    if (Convert.ToBoolean(notify & 0x80000000))
                    {
                        System.Console.Write("批处理重新开始!\n");
                        m_curBatchNo = 0;
                    }

                    if (Convert.ToBoolean(notify & 0x04))
                    {
                        System.Console.Write("新批处理!\n");
                    }
                }











                //for (int i = 0; i < count; i++)
                //{
                //    //保存图像
                //    if (m_bEnableRevData && m_CurrentProfile < m_NeededProfile)
                //    {
                //        //adValueZ = adValueX.Zip(adValueZ, (a, b) => b + a * m_tanValue * Convert.ToInt16(Convert.ToBoolean(b))).ToArray();
                //        uint profileSize = size / sizeof(int);
                //        int[] bufferArray = new int[profileSize * count];
                //        int[] adValueZ = new int[profileInfo.wProfDataCnt * count];
                //        int headerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_HEADER)) / sizeof(int);
                //        Marshal.Copy(buffer, bufferArray, 0, (int)(profileSize * count));
                //        Array.Copy(bufferArray, headerSize, adValueZ, 0, profileInfo.wProfDataCnt * count);
                //        //Marshal.Copy(buffer, bufferArray, headerSize, (int)(profileInfo.wProfDataCnt * count));
                //        //adValueZ = Array.ConvertAll(bufferArray, d => d / 100000.0);//本质上是遍历

                //        if (heightImage == null || !heightImage.IsInitialized())
                //        {
                //            m_bEnableRevData = false;
                //            return;
                //        }
                //        //m_Image.SetGrayval(HTuple.TupleGenConst(800, m_CurrentProfile), HTuple.TupleGenSequence(0, 800 - 1, 1), (new HTuple(adValueZ)).TupleDiv(100000));
                //        heightImage.SetGrayval(HTuple.TupleGenConst(profileInfo.wProfDataCnt, m_CurrentProfile), HTuple.TupleGenSequence(0, profileInfo.wProfDataCnt - 1, 1), (new HTuple(adValueZ)).TupleDiv(100.0));
                //        m_CurrentProfile++;
                //    }
                //    else if (m_bEnableRevData && m_CurrentProfile == m_NeededProfile)
                //    {
                //        m_bEnableRevData = false;
                //        //使用委托传递出去
                //        heightImageEvent.Set();
                //    }
                //}
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                return;
            }
        }

        public bool Start()
        {
            Rc rc = Rc.Ok;

            heightImage = new HImage("real", (int)profileInfo.wProfDataCnt, m_NeededProfile);
            m_bEnableRevData = true;
            m_CurrentProfile = 0;

            rc = (Rc)NativeMethods.LJV7IF_StartMeasure(DEVICE_ID);
            return CheckReturnCode(rc);
        }

        public bool Stop()
        {
            Rc rc = Rc.Ok;
            if (m_bEnableRevData == true)
            {
                m_bEnableRevData = false;
                heightImageEvent.Set();
            }
            rc = (Rc)NativeMethods.LJV7IF_StopMeasure(DEVICE_ID);
            return CheckReturnCode(rc);
        }
    }

    public class LJX8Laser : ILineLaser
    {

        /// <summary>
        /// 采集帧数，只对线扫设备有效
        /// </summary>
        public int m_NeededProfile { get; set; }

        /// <summary>
        /// 采集帧数，只对线扫设备有效
        /// </summary>
        protected int m_CurrentProfile = 0;

        [NonSerialized]
        public bool m_bEnableRevData = false;//回调函数时，是否允许接受数据

        private HImage heightImage;
        private HImage luminanceImage;
        private AutoResetEvent heightImageEvent = new AutoResetEvent(false);
        private AutoResetEvent luminanceImageEvent = new AutoResetEvent(false);
        public HImage HeightImage(int timeout = 3000)
        {
            if (heightImageEvent.WaitOne(timeout) == true)
            {
                if (heightImage.IsInitialized())
                {
                    return heightImage.CopyImage();
                }
            }

            return null;
        }
        public HImage LuminanceImage(int timeout = 3000)
        {
            if (luminanceImageEvent.WaitOne(timeout) == true)
            {
                if (luminanceImage.IsInitialized())
                {
                    return luminanceImage.CopyImage();
                }
            }
            return null;
        }



        bool m_bConnected = false;
        public bool IsConnected
        {
            get
            {
                return m_bConnected;
            }
        }

        public static int DEVICE_COUNT = 0;
        /// <summary>Device ID (fixed to 0)</summary>
        private int DEVICE_ID = 0;//0~5

        /// <summary>Ethernet communication settings</summary>
        public string m_UniqueLabel
        {
            get { return ethernetConfig.abyIpAddress.ToString() + ":" + ethernetConfig.wPortNo.ToString(); }
            set
            {
                //设置keyence ip地址
                string[] ipInfo = value.Split(':');
                string[] keyenceIp = ipInfo[0].Split('.');
                ethernetConfig.abyIpAddress = new byte[] {
                Convert.ToByte(keyenceIp[0]),
                Convert.ToByte(keyenceIp[1]),
                Convert.ToByte(keyenceIp[2]),
                Convert.ToByte(keyenceIp[3])
                };
                ethernetConfig.wPortNo = (ushort)(int.Parse(ipInfo[1]));
                highSpeedPort = (ushort)(ethernetConfig.wPortNo + 1);
            }
        }

        /// <summary>Ethernet communication port settings</summary>
        private UInt16 _highSpeedPort;

        /// <summary>connection mode 默认1  0 -USB 连接模式 1 - 高速网口连接模式，</summary>
        private int _connectMode = 1;

        /// <summary>批处理多少帧回调一次，默认每帧回调一次，设置单帧回调，目的是避免存留在内存里</summary>
        private uint _profileFrequence = 1;

        /// <summary>High-speed communication start profileNO</summary>
        private byte _StartProfileNo = 0;

        /// <summary>量程上下限</summary>
        private double LimitMin = -7.5;
        private double LimitMax = 7.5;

        /// <summary>
        /// 输出数据模式，0- 返回所有数据 1- 返回第一个镭射数据，2 -返回第二个镭射数据
        /// </summary>
        private int _outDataMode = 0;

        /// <summary>High-speed communication callback function</summary>
        [NonSerialized]
        //private HighSpeedDataCallBack _callback;
        //private HighSpeedDataCallBack _callback;
        private HighSpeedDataCallBackForSimpleArray _callback;

        /// <summary>the size of header and footer</summary>
        //[NonSerialized]
        //int headerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_HEADER)) / sizeof(int);
        //[NonSerialized]
        //int footerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_FOOTER)) / sizeof(int);

        LJX8IF_PROFILE_INFO profileInfo = new LJX8IF_PROFILE_INFO();
        LJX8IF_HIGH_SPEED_PRE_START_REQUEST req = new LJX8IF_HIGH_SPEED_PRE_START_REQUEST();
        //图像指针内存

        //IntPtr Imagebuffer;
        //int[] reciveBuffer;

        ///// <summary>统计接收到的帧数</summary>
        //private int _receiveCount = 0;

        /// <summary>
        /// 基恩士激光网卡设置
        /// </summary>
        private LJX8IF_ETHERNET_CONFIG ethernetConfig;
        private int m_curBatchNo;

        //高速采集网络端口号
        public UInt16 highSpeedPort
        {
            get { return _highSpeedPort; }
            set { _highSpeedPort = value; }
        }
        //连接模式
        public int connectMode
        {
            get { return _connectMode; }
            set { _connectMode = value; }
        }
        //采集频率
        public uint frequence
        {
            get { return _profileFrequence; }
            set { _profileFrequence = value; }
        }
        //开始采集位置
        public byte StartProfileNo
        {
            get { return _StartProfileNo; }
            set { _StartProfileNo = value; }
        }
        /// <summary>
        /// 返回数据模式
        /// </summary>
        public int OutDataMode
        {
            get { return _outDataMode; }
            set { _outDataMode = value; }
        }


        public LJX8Laser(int devID, string ip = "192.168.0.15", ushort portNo = 24691, ushort highSpeedPortNo = 24692)
        {
            DEVICE_ID = devID;
            string[] ips = ip.Split('.');

            byte[] ipAddress = new byte[4];
            if (!byte.TryParse(ips[0], out ipAddress[0]) ||
                !byte.TryParse(ips[1], out ipAddress[1]) ||
                !byte.TryParse(ips[2], out ipAddress[2]) ||
                !byte.TryParse(ips[3], out ipAddress[3]))
            {
                Debug.WriteLine("LJX8激光IP格式不正确!");
                return;
            }

            ethernetConfig.abyIpAddress = ipAddress;
            ethernetConfig.wPortNo = portNo;

            highSpeedPort = highSpeedPortNo;
            req = new LJX8IF_HIGH_SPEED_PRE_START_REQUEST();
            req.bySendPosition = Convert.ToByte("2");
            //

        }

        /// <summary>
        ///停止中断设备连接
        ////// <summary>
        public void  DisConnect()
        {
            try
            {
                //Marshal.FreeHGlobal(Imagebuffer);
                //reciveBuffer = null;

                Rc rc = Rc.Ok;

                // Stop high-speed data communication.
                rc = (Rc)NativeMethods_LJX8.LJX8IF_StopHighSpeedDataCommunication(DEVICE_ID);
                if (CheckReturnCode(rc))
                {
                    // Exit high-speed data communication.
                    rc = (Rc)NativeMethods_LJX8.LJX8IF_FinalizeHighSpeedDataCommunication(DEVICE_ID);
                    if (CheckReturnCode(rc))
                    {
                        rc = (Rc)NativeMethods_LJX8.LJX8IF_CommunicationClose(DEVICE_ID);
                        if (CheckReturnCode(rc))
                        {
                            rc = (Rc)NativeMethods_LJX8.LJX8IF_Finalize();
                            m_bConnected = false;
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// The check of a return code 
        /// </summary>
        /// <param name="rc">Return code </param>
        /// <returns>OK or not</returns>
        /// <remarks>If not OK, return false after displaying message.</remarks>
        private bool CheckReturnCode(Rc rc)
        {
            if (rc == Rc.Ok) return true;
            //MessageBox.Show(string.Format("Error: 0x{0,8:x}", rc), "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
        /// <summary>
        /// 开始采集数据
        /// </summary>
        public Boolean InitDevice()
        {
            try
            {
                Rc rc = Rc.Ok;
                //clear all data in buffer
                rc = (Rc)NativeMethods_LJX8.LJX8IF_ClearMemory(DEVICE_ID);
                if (CheckReturnCode(rc))
                {
                    rc = (Rc)NativeMethods_LJX8.LJX8IF_StopHighSpeedDataCommunication(DEVICE_ID);
                    if (CheckReturnCode(rc))
                    {
                        rc = (Rc)NativeMethods_LJX8.LJX8IF_FinalizeHighSpeedDataCommunication(DEVICE_ID);
                        if (CheckReturnCode(rc))
                        {

                            uint threadId = (uint)(DEVICE_ID);// + 1

                            _callback = new HighSpeedDataCallBackForSimpleArray(ReceiveHighSpeedSimpleArray);

                            // Initialize Ethernet high-speed data communication
                            rc = (Rc)NativeMethods_LJX8.LJX8IF_InitializeHighSpeedDataCommunicationSimpleArray(DEVICE_ID, ref ethernetConfig, highSpeedPort, _callback, frequence, threadId);

                            if (CheckReturnCode(rc))
                            {
                                // High-speed data communication start prep
                                rc = (Rc)NativeMethods_LJX8.LJX8IF_PreStartHighSpeedDataCommunication(DEVICE_ID, ref req, ref profileInfo);

                                if (CheckReturnCode(rc))
                                {
                                    rc = (Rc)NativeMethods_LJX8.LJX8IF_StartHighSpeedDataCommunication(DEVICE_ID);
                                    if (CheckReturnCode(rc))
                                    {
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }

                return false;

                //接受到连接信息后初始化
                //Imagebuffer = Marshal.AllocHGlobal(m_NeededProfile * (DEVICE_ID + 1) * profileInfo.wProfDataCnt * sizeof(int));
                //reciveBuffer = new int[profileInfo.wProfDataCnt * (DEVICE_ID + 1) * m_NeededProfile];
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool DLLInit()
        {
            Rc rc = Rc.Ok;
            // Initialize the DLL.
            rc = (Rc)NativeMethods_LJX8.LJX8IF_Initialize();
            return CheckReturnCode(rc);
        }

        public bool Connect(string id)
        {
            DisConnect();
            Rc rc = Rc.Ok;
            // Initialize the DLL.
            //rc = (Rc)NativeMethods_LJX8.LJX8IF_Initialize();
            if (CheckReturnCode(rc))
            {
                // Open communication path.
                rc = (Rc)NativeMethods_LJX8.LJX8IF_EthernetOpen(DEVICE_ID, ref ethernetConfig);
                if (rc != Rc.Ok)
                {
                    rc = (Rc)NativeMethods_LJX8.LJX8IF_EthernetOpen(DEVICE_ID, ref ethernetConfig);
                }

                if (CheckReturnCode(rc))
                {
                    if (InitDevice())
                    {
                        m_bConnected = true;
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// High-speed communication callback process
        /// </summary>
        /// <param name="buffer">Pointer to beginning of received data</param>
        /// <param name="size">Byte size per 1 profile in received data</param>
        /// <param name="count">Profile count</param>
        /// <param name="notify">Exited or not</param>
        /// <param name="user">Information passed when high-speed data communication was initialized (thread ID)</param>
        private void ReceiveData(IntPtr buffer, uint size, uint count, uint notify, uint user)
        {
            try
            {
                if (notify != 0)
                {
                    if (Convert.ToBoolean(notify & 0x08))
                    {
                        NativeMethods_LJX8.LJX8IF_StopMeasure(DEVICE_ID);
                    }
                }

                //if (count == 0 || size == 0)
                //    return;

                uint profileSize = (uint)(size / Marshal.SizeOf(typeof(int)));   //轮廓宽度

                List<int[]> receiveBuffer = new List<int[]>();
                int[] bufferArray = new int[profileSize * count];
                Marshal.Copy(buffer, bufferArray, 0, (int)(profileSize * count));

                // Profile data retention
                for (int i = 0; i < count; i++)
                {
                    int[] oneProfile = new int[profileSize];
                    Array.Copy(bufferArray, i * profileSize, oneProfile, 0, profileSize);
                    receiveBuffer.Add(oneProfile);
                }

                ThreadSafeBuffer_LJX8.Add((int)user, receiveBuffer, notify);

                if (notify != 0)
                {
                    if (notify == 0x10000)
                    {
                        NativeMethods_LJX8.LJX8IF_StopMeasure(DEVICE_ID);
                        System.Console.Write("数据接收完成!\n");
                        int batcnNo = 0;

                        List<int[]> data = ThreadSafeBuffer_LJX8.Get(DEVICE_ID, out notify, out batcnNo);

                        int ss = data[0].Length;
                        using (PinnedObject pin = new PinnedObject(data))
                        {
                            IntPtr bufferPointer = pin.Pointer;

                            heightImage = new HImage();
                            heightImage.GenImage1("int4", (int)profileSize, data.Count, bufferPointer);
                            heightImage = heightImage.ConvertImageType("real");
                            heightImage = heightImage.ScaleImage(1 / 100000.0, 0);
                        }
                        m_curBatchNo = 0;
                        heightImageEvent.Set();
                        ThreadSafeBuffer_LJX8.ClearBuffer(DEVICE_ID);
                    }
                    if (Convert.ToBoolean(notify & 0x80000000))
                    {
                        System.Console.Write("批处理重新开始!\n");
                        m_curBatchNo = 0;
                    }

                    if (Convert.ToBoolean(notify & 0x04))
                    {
                        System.Console.Write("新批处理!\n");
                    }
                }



                //for (int i = 0; i < count; i++)
                //{
                //    //保存图像
                //    if (m_bEnableRevData && m_CurrentProfile < m_NeededProfile)
                //    {
                //        //adValueZ = adValueX.Zip(adValueZ, (a, b) => b + a * m_tanValue * Convert.ToInt16(Convert.ToBoolean(b))).ToArray();
                //        uint profileSize = size / sizeof(int);
                //        int[] bufferArray = new int[profileSize * count];
                //        int[] adValueZ = new int[profileInfo.wProfDataCnt * count];
                //        int headerSize = Marshal.SizeOf(typeof(LJV7IF_PROFILE_HEADER)) / sizeof(int);
                //        Marshal.Copy(buffer, bufferArray, 0, (int)(profileSize * count));
                //        Array.Copy(bufferArray, headerSize, adValueZ, 0, profileInfo.wProfDataCnt * count);
                //        //Marshal.Copy(buffer, bufferArray, headerSize, (int)(profileInfo.wProfDataCnt * count));
                //        //adValueZ = Array.ConvertAll(bufferArray, d => d / 100000.0);//本质上是遍历

                //        if (heightImage == null || !heightImage.IsInitialized())
                //        {
                //            m_bEnableRevData = false;
                //            return;
                //        }
                //        //m_Image.SetGrayval(HTuple.TupleGenConst(800, m_CurrentProfile), HTuple.TupleGenSequence(0, 800 - 1, 1), (new HTuple(adValueZ)).TupleDiv(100000));
                //        heightImage.SetGrayval(HTuple.TupleGenConst(profileInfo.wProfDataCnt, m_CurrentProfile), HTuple.TupleGenSequence(0, profileInfo.wProfDataCnt - 1, 1), (new HTuple(adValueZ)).TupleDiv(100.0));
                //        m_CurrentProfile++;
                //    }
                //    else if (m_bEnableRevData && m_CurrentProfile == m_NeededProfile)
                //    {
                //        m_bEnableRevData = false;
                //        //使用委托传递出去
                //        heightImageEvent.Set();
                //    }
                //}
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                return;
            }
        }


        List<short> receiveBuffer = new List<short>();
        private void ReceiveHighSpeedSimpleArray(IntPtr headBuffer, IntPtr profileBuffer, IntPtr luminanceBuffer, uint isLuminanceEnable, uint profileSize, uint count, uint notify, uint user)
        {
            // @Point
            // Take care to only implement storing profile data in a thread save buffer in the callback function.
            // As the thread used to call the callback function is the same as the thread used to receive data,
            // the processing time of the callback function affects the speed at which data is received,
            // and may stop communication from being performed properly in some environments.

            if (notify != 0)
            {
                if (Convert.ToBoolean(notify & 0x08))
                {
                    NativeMethods_LJX8.LJX8IF_StopMeasure(DEVICE_ID);
                }
            }

            short[] bufferArray = new short[profileSize * count];
            Marshal.Copy(profileBuffer, bufferArray, 0, (int)(profileSize * count));
            receiveBuffer.AddRange(bufferArray);

            if (notify != 0)
            {
                if (notify == 0x10000)
                {
                    int heigt = receiveBuffer.Count / (int)profileSize;
                    short[] BuffArray = receiveBuffer.ToArray();
                    IntPtr intPtr = Marshal.UnsafeAddrOfPinnedArrayElement(BuffArray, 0);
                    heightImage = new HImage();
                    heightImage.GenImage1("uint2", (int)profileSize, heigt, intPtr);
                    heightImage = heightImage.ConvertImageType("real");
                    heightImage = heightImage.ScaleImage(0.8 * 0.001, (-32768) * 0.8 * 0.001);//1 / 100000.0
                    //heightImage.WriteImage("tiff" , 0 , "D:\\代码\\Quebec-AFMT-RHorn-20240328\\123.tiff");
                    receiveBuffer.Clear();
                    heightImageEvent.Set();

                    //NativeMethods_LJX8.LJX8IF_StopMeasure(DEVICE_ID);
                    //System.Console.Write("数据接收完成!\n");
                    //int batcnNo = 0;

                    //List<int[]> data = ThreadSafeBuffer_LJX8.Get(DEVICE_ID, out notify, out batcnNo);

                    //int ss = data[0].Length;
                    //using (PinnedObject pin = new PinnedObject(data))
                    //{
                    //    IntPtr bufferPointer = pin.Pointer;

                    //    heightImage = new HImage();
                    //    heightImage.GenImage1("int4", (int)profileSize, data.Count, bufferPointer);
                    //    heightImage = heightImage.ConvertImageType("real");
                    //    heightImage = heightImage.ScaleImage(1 / 100000.0, 0);
                    //}
                    //m_curBatchNo = 0;
                    //heightImageEvent.Set();
                    //ThreadSafeBuffer_LJX8.ClearBuffer(DEVICE_ID);
                }
                if (Convert.ToBoolean(notify & 0x80000000))
                {
                    System.Console.Write("批处理重新开始!\n");
                    m_curBatchNo = 0;
                }

                if (Convert.ToBoolean(notify & 0x04))
                {
                    System.Console.Write("新批处理!\n");
                }
            }
        }


        public bool Start()
        {
            Rc rc = Rc.Ok;
            //heightImage = new HImage("real", (int)profileInfo.nProfileDataCount, m_NeededProfile);
            m_bEnableRevData = true;
            m_CurrentProfile = 0;
            receiveBuffer.Clear();
            rc = (Rc)NativeMethods_LJX8.LJX8IF_StartMeasure(DEVICE_ID);
            return CheckReturnCode(rc);
        }

        public bool Stop()
        {
            Rc rc = Rc.Ok;
            if (m_bEnableRevData == true)
            {
                m_bEnableRevData = false;
                // heightImageEvent.Set();
            }
            rc = (Rc)NativeMethods_LJX8.LJX8IF_StopMeasure(DEVICE_ID);
            return CheckReturnCode(rc);
        }

        public bool ChangeActiveProgram(byte byProgramNo)
        {
            byte byActiveProgramNo = 0;
            var ret = GetActiveProgram(ref byActiveProgramNo);
            if (ret && byActiveProgramNo == byProgramNo)
            {
                return true;
            }
            else
            {
                int rc = NativeMethods_LJX8.LJX8IF_ChangeActiveProgram(DEVICE_ID, byProgramNo);
                if (rc == (int)Rc.Ok)
                {
                    //切换需要重启高速通道
                    if (InitDevice())
                        return true;
                    else
                        return false;
                }
                else
                    return false;
            }

        }

        public bool GetActiveProgram(ref byte programNo)
        {
            programNo = 0;
            int rc = NativeMethods_LJX8.LJX8IF_GetActiveProgram(DEVICE_ID, ref programNo);
            if (rc == (int)Rc.Ok)
                return true;
            else
                return false;

        }

    }

    public static class ThreadSafeBuffer
    {
        #region Field
        /// <summary>Data buffer</summary>
        private static List<int[]>[] _buffer = new List<int[]>[NativeMethods.DeviceCount];
        /// <summary>Buffer for the amount of data</summary>
        private static uint[] _count = new uint[NativeMethods.DeviceCount];
        /// <summary>Object for exclusive control</summary>
        private static object[] _syncObject = new object[NativeMethods.DeviceCount];
        /// <summary>Callback function notification parameter</summary>
        private static uint[] _notify = new uint[NativeMethods.DeviceCount];
        /// <summary>Batch number</summary>
        private static int[] _batchNo = new int[NativeMethods.DeviceCount];
        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        static ThreadSafeBuffer()
        {
            for (int i = 0; i < NativeMethods.DeviceCount; i++)
            {
                _buffer[i] = new List<int[]>();
                _syncObject[i] = new object();
            }
        }
        #endregion

        #region Method
        /// <summary>
        /// Element addition
        /// </summary>
        /// <param name="index">User information set when high-speed communication was initialized</param>
        /// <param name="value">Additional element</param>
        /// <param name="notify">Parameter for notification</param>
        public static void Add(int index, List<int[]> value, uint notify)
        {
            lock (_syncObject[index])
            {
                _buffer[index].AddRange(value);
                _count[index] += (uint)value.Count;
                _notify[index] |= notify;
                // Add the batch number if the batch has been finalized.
                if ((notify & (0x1 << 16)) != 0) _batchNo[index]++;
            }
        }

        /// <summary>
        /// Clear elements.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void Clear(int _currentDeviceId)
        {
            lock (_syncObject[_currentDeviceId])
            {
                _buffer[_currentDeviceId].Clear();
            }
        }

        /// <summary>
        /// Clear the number of elements.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void ClearCount(int index)
        {
            lock (_syncObject[index])
            {
                _count[index] = 0;
            }
        }

        /// <summary>
        /// Clear notifications.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void ClearNotify(int index)
        {
            lock (_syncObject[index])
            {
                _notify[index] = 0;
            }
        }

        /// <summary>
        /// Clear elements.
        /// </summary>
        public static void ClearAll()
        {
            for (int i = 0; i < NativeMethods.DeviceCount; i++)
            {
                ClearBuffer(i);
            }
        }

        /// <summary>
        /// Clear the buffer.
        /// </summary>
        /// <param name="_currentDeviceId">Device ID</param>
        public static void ClearBuffer(int _currentDeviceId)
        {
            Clear(_currentDeviceId);
            ClearCount(_currentDeviceId);
            _batchNo[_currentDeviceId] = 0;
            ClearNotify(_currentDeviceId);
        }

        /// <summary>
        /// Get element.
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="notify">Parameter for notification</param>
        /// <param name="batchNo">Batch number</param>
        /// <returns>Element</returns>
        public static List<int[]> Get(int index, out uint notify, out int batchNo)
        {
            List<int[]> value = new List<int[]>();
            lock (_syncObject[index])
            {
                foreach (int[] data in _buffer[index])
                {
                    value.Add(data);
                }
                _buffer[index].Clear();
                notify = _notify[index];
                _notify[index] = 0;
                batchNo = _batchNo[index];
            }
            return value;
        }

        /// <summary>
        /// Add the count
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="count">Count</param>
        /// <param name="notify">Parameter for notification</param>
        internal static void AddCount(int index, uint count, uint notify)
        {
            lock (_syncObject[index])
            {
                _count[index] += count;
                _notify[index] |= notify;
                // Add the batch number if the batch has been finalized.
                if ((notify & (0x1 << 16)) != 0) _batchNo[index]++;
            }
        }

        /// <summary>
        /// Get the count
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="notify">Parameter for notification</param>
        /// <param name="batchNo">Batch number</param>
        /// <returns></returns>
        internal static uint GetCount(int index, out uint notify, out int batchNo)
        {
            lock (_syncObject[index])
            {
                notify = _notify[index];
                _notify[index] = 0;
                batchNo = _batchNo[index];
                return _count[index];
            }
        }

        #endregion
    }

    public static class ThreadSafeBuffer_LJX8
    {
        #region Field
        /// <summary>Data buffer</summary>
        private static List<int[]>[] _buffer = new List<int[]>[NativeMethods_LJX8.DeviceCount];
        /// <summary>Buffer for the amount of data</summary>
        private static uint[] _count = new uint[NativeMethods_LJX8.DeviceCount];
        /// <summary>Object for exclusive control</summary>
        private static object[] _syncObject = new object[NativeMethods_LJX8.DeviceCount];
        /// <summary>Callback function notification parameter</summary>
        private static uint[] _notify = new uint[NativeMethods_LJX8.DeviceCount];
        /// <summary>Batch number</summary>
        private static int[] _batchNo = new int[NativeMethods_LJX8.DeviceCount];
        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        static ThreadSafeBuffer_LJX8()
        {
            for (int i = 0; i < NativeMethods_LJX8.DeviceCount; i++)
            {
                _buffer[i] = new List<int[]>();
                _syncObject[i] = new object();
            }
        }
        #endregion

        #region Method
        /// <summary>
        /// Element addition
        /// </summary>
        /// <param name="index">User information set when high-speed communication was initialized</param>
        /// <param name="value">Additional element</param>
        /// <param name="notify">Parameter for notification</param>
        public static void Add(int index, List<int[]> value, uint notify)
        {
            lock (_syncObject[index])
            {
                _buffer[index].AddRange(value);
                _count[index] += (uint)value.Count;
                _notify[index] |= notify;
                // Add the batch number if the batch has been finalized.
                if ((notify & (0x1 << 16)) != 0) _batchNo[index]++;
            }
        }

        /// <summary>
        /// Clear elements.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void Clear(int _currentDeviceId)
        {
            lock (_syncObject[_currentDeviceId])
            {
                _buffer[_currentDeviceId].Clear();
            }
        }

        /// <summary>
        /// Clear the number of elements.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void ClearCount(int index)
        {
            lock (_syncObject[index])
            {
                _count[index] = 0;
            }
        }

        /// <summary>
        /// Clear notifications.
        /// </summary>
        /// <param name="index">Device ID</param>
        public static void ClearNotify(int index)
        {
            lock (_syncObject[index])
            {
                _notify[index] = 0;
            }
        }

        /// <summary>
        /// Clear elements.
        /// </summary>
        public static void ClearAll()
        {
            for (int i = 0; i < NativeMethods_LJX8.DeviceCount; i++)
            {
                ClearBuffer(i);
            }
        }

        /// <summary>
        /// Clear the buffer.
        /// </summary>
        /// <param name="_currentDeviceId">Device ID</param>
        public static void ClearBuffer(int _currentDeviceId)
        {
            Clear(_currentDeviceId);
            ClearCount(_currentDeviceId);
            _batchNo[_currentDeviceId] = 0;
            ClearNotify(_currentDeviceId);
        }

        /// <summary>
        /// Get element.
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="notify">Parameter for notification</param>
        /// <param name="batchNo">Batch number</param>
        /// <returns>Element</returns>
        public static List<int[]> Get(int index, out uint notify, out int batchNo)
        {
            List<int[]> value = new List<int[]>();
            lock (_syncObject[index])
            {
                //foreach (int[] data in _buffer[index])
                //{
                //    value.Add(data);
                //}

                value.AddRange(_buffer[index]);
                _buffer[index].Clear();
                notify = _notify[index];
                _notify[index] = 0;
                batchNo = _batchNo[index];
            }
            return value;
        }

        /// <summary>
        /// Add the count
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="count">Count</param>
        /// <param name="notify">Parameter for notification</param>
        internal static void AddCount(int index, uint count, uint notify)
        {
            lock (_syncObject[index])
            {
                _count[index] += count;
                _notify[index] |= notify;
                // Add the batch number if the batch has been finalized.
                if ((notify & (0x1 << 16)) != 0) _batchNo[index]++;
            }
        }

        /// <summary>
        /// Get the count
        /// </summary>
        /// <param name="index">Device ID</param>
        /// <param name="notify">Parameter for notification</param>
        /// <param name="batchNo">Batch number</param>
        /// <returns></returns>
        internal static uint GetCount(int index, out uint notify, out int batchNo)
        {
            lock (_syncObject[index])
            {
                notify = _notify[index];
                _notify[index] = 0;
                batchNo = _batchNo[index];
                return _count[index];
            }
        }

        #endregion
    }
}
